package com.example.wlzz.controller;
import com.example.wlzz.api.ConfigAPI;
import com.example.wlzz.dto.*;
import com.example.wlzz.enums.ResultEnum;
import com.example.wlzz.form.CrawlerForm;
import com.example.wlzz.repository.DepartmentWebRepository;
import com.example.wlzz.repository.mongoRepository.KlassRepository;
import com.example.wlzz.service.UserInfoService;
import com.example.wlzz.utils.CodeRequestUtil;
import com.example.wlzz.utils.ResultVOUtil;
import com.example.wlzz.utils.StrToListForIntUtil;
import com.example.wlzz.vo.CodeVO;
import com.example.wlzz.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/mongoliaCrawler")
@Slf4j
@Api(tags = "蒙古科技大学爬虫模块")
public class MongoliaCrawlerController {
    @Autowired
    private ConfigAPI configAPI;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private DepartmentWebRepository departmentWebRepository;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private KlassRepository klassRepository;
    @PostMapping("/first")
    @ApiOperation("第一步：进入这里获取登陆的cookie和验证码")
    public ResultVO first(@ApiParam("token") @RequestParam("token") String token){
        try {
            Connection con = Jsoup.connect("http://202.207.80.11");
            con.header("User-Agent",
                    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");// 配置模拟浏览器
            Connection.Response rs = con.timeout(10000).execute();// 获取响应
            Map<String,String> cookies = rs.cookies();
            CodeVO codeVO =  CodeRequestUtil.codeRequest("http://202.207.80.11/validateCodeAction.do?random=0.66666666",cookies,configAPI.getName());
            return ResultVOUtil.success(codeVO);
        }catch (Exception e){
            e.printStackTrace();
            return ResultVOUtil.error(ResultEnum.GET_CLASS_ERROR.getCode(),ResultEnum.GET_CLASS_ERROR.getMessage());
        }
    }
    @PostMapping("/second")
    @ApiOperation("第二步：将【第一步】拿到的cookie放进对应的输入框里(登陆成功则返回对应的cookie)【提示：登陆成功将会更新个人信息的学号和密码】")
    public ResultVO second(@Valid CrawlerForm crawlerForm , BindingResult bindingResult, @ApiParam("token") @RequestParam("token") String token)throws Exception{
        if(bindingResult.hasErrors()) {
            return ResultVOUtil.error(ResultEnum.LOGIN_SCHOOL_ERROR.getCode(),ResultEnum.LOGIN_SCHOOL_ERROR.getMessage());
        }
        Map<String,String> cookies = new HashMap<>();
        String[] array = crawlerForm.getCookie().split("=");
        cookies.put(array[0],array[1]);

        Map<String, String> datas = new HashMap<>();  //参数
        //无用参数
        datas.put("zjh1","");
        datas.put("tips","");
        datas.put("lx","");
        datas.put("evalue","");
        datas.put("eflag","");
        datas.put("fs","");
        datas.put("dzslh","");
        //真实需要参数
        datas.put("zjh",crawlerForm.getSno());
        datas.put("mm",crawlerForm.getPasswd());
        datas.put("v_yzm", crawlerForm.getCode()); //验证码
        Connection con2 = Jsoup
                .connect("http://202.207.80.11/loginAction.do");
        con2.header("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");
        // 设置cookie和post上面的map数据
        Connection.Response login = con2.ignoreContentType(true).method(Connection.Method.POST)
                .data(datas).cookies(cookies).timeout(10000).execute();
        Document document = login.parse();
        if("学分制综合教务".equals(document.title())){
            userInfoService.alterSnoAndSnoPassword(crawlerForm.getSno(),crawlerForm.getPasswd(),token);//更改用户的学号和密码

            CookieDTO cookieDTO = new CookieDTO();
            cookieDTO.setCookies(array[0]+"="+array[1]);
            return ResultVOUtil.success(cookieDTO);
         //   return ResultVOUtil.success(crawlerForm.getCookie());
        }else{
            return ResultVOUtil.error(ResultEnum.SNO_ERROR.getCode(), ResultEnum.SNO_ERROR.getMessage());
        }
    }
    @PostMapping("/getNowClass")
    @ApiOperation("获得当前学期课表")
    public ResultVO getNowClass(@ApiParam("token") @RequestParam("token") String token,
                                 @RequestParam("cookie") String cookie){
            //http://202.207.80.11/xkAction.do?actionType=6
        Map<String,String> cookies = new HashMap<>();
        String[] array = cookie.split("=");
        cookies.put(array[0],array[1]);
        Connection con2 = Jsoup
                .connect("http://202.207.80.11/xkAction.do?actionType=6");
        con2.header("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");
        // 设置cookie和post上面的map数据
        try {
            Connection.Response login = con2.ignoreContentType(true).method(Connection.Method.POST)
                    .cookies(cookies).timeout(10000).execute();
            Document document = login.parse(); // 这里就是得到HTML文本
            Elements elements = document.getElementsByClass("titleTop2");
            String klass = elements.get(1).toString();
            Document document2 = Jsoup.parse(klass);
            Elements trElements = document2.getElementsByClass("odd");
            List<NewKlassContent> newKlassContents = new ArrayList<>();
            NewKlassContent newKlassContentTemple = new NewKlassContent(); // 其实是一个临时的变量
            for (Element element : trElements) {
                Elements tdElements = element.getElementsByTag("td");
                // System.out.print(tdElements.get(i).text()+" ");
                String pattern = "^[0-9]*$";
                boolean isMatch = Pattern.matches(pattern, tdElements.get(0).text());
                NewKlassContent newKlassContent = new NewKlassContent();
                if (isMatch) { // 一般一开始都是先走这个
                    // 给模板增添信息
                    newKlassContentTemple.setName(tdElements.get(1).text());
                    newKlassContentTemple.setTeacher(tdElements.get(6).text());
                    // 给自己的实体类增加相应信息
                    newKlassContent.setName(tdElements.get(1).text());
                    newKlassContent.setTeacher(tdElements.get(6).text());

                    String week = tdElements.get(10).text();
                    if (week.length() == 0) { // 直接跳过
                        continue;
                    }
                    List<Integer> inList = StrToListForIntUtil.getList(week);
                    newKlassContent.setWeekList(inList);
                    newKlassContent.setDay(Integer.valueOf(tdElements.get(11).text()));
                    newKlassContent.setStart(2 * Integer.valueOf(tdElements.get(12).text()) - 1);
                    newKlassContent.setStep(Integer.valueOf(tdElements.get(13).text()));
                    String classRoom = ("空".equals(tdElements.get(16).text())) ? "" : tdElements.get(16).text(); // 是否为空
                    newKlassContent.setRoom(tdElements.get(14).text() + tdElements.get(15).text() + classRoom);
                } else { // 这里只有周次等信息没有相对应的课程信息则使用模板
                    // 从模板获取信息
                    newKlassContent.setName(newKlassContentTemple.getName());
                    newKlassContent.setTeacher(newKlassContentTemple.getTeacher());
                    // 自己获取信息
                    String week = tdElements.get(0).text();
                    if (week.length() == 0) { // 忽略没有周次的课程，因为前端都无法显示则忽略
                        continue;
                    }
                    List<Integer> inList =  StrToListForIntUtil.getList(week);
                    newKlassContent.setWeekList(inList);
                    newKlassContent.setDay(Integer.valueOf(tdElements.get(1).text()));
                    newKlassContent.setStart(2 * Integer.valueOf(tdElements.get(2).text()) - 1);
                    newKlassContent.setStep(Integer.valueOf(tdElements.get(3).text()));
                    String classRoom = ("空".equals(tdElements.get(6).text())) ? "" : tdElements.get(6).text(); // 是否为空
                    newKlassContent.setRoom(tdElements.get(4).text() + tdElements.get(5).text() + classRoom);
                }

                newKlassContents.add(newKlassContent);
            }
//            KlassForUser klassForUser = new KlassForUser();
//            //去redis查询
//            String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.LOGIN_SUCCESS_TOKEN, token));
//            klassForUser.set_id(tokenValue);
//            klassForUser.setKlassContent(newKlassContents);
//            klassRepository.save(klassForUser);
            return ResultVOUtil.success(newKlassContents);
        }catch (Exception e){
            e.printStackTrace();
            return ResultVOUtil.error(ResultEnum.GET_CLASS_ERROR.getCode(),ResultEnum.GET_CLASS_ERROR.getMessage());
        }
    }

    @PostMapping("/getDepartment")
    @ApiOperation("获得内蒙古科技大学的院系")
    public ResultVO getDepartment(@ApiParam("token") @RequestParam("token") String token){
        //http://202.207.80.11/xkAction.do?actionType=6
//        Map<String,String> cookies = new HashMap<>();
//        String[] array = cookie.split("=");
//        cookies.put(array[0],array[1]);
//        Connection con2 = Jsoup
//                .connect("http://202.207.80.11/bjkbcxAction.do?oper=bjkb_lb");
//        con2.header("User-Agent",
//                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");
//        // 设置cookie和post上面的map数据
//        try {
//            Connection.Response login = con2.ignoreContentType(true).method(Connection.Method.GET)
//                    .cookies(cookies).execute();
//            Document document = login.parse();
//            Elements elements = document.getElementsByTag("select");
//            Element e  = elements.get(1);   //获取院系
//            Elements options = e.getElementsByTag("option");
//            List<MajorKlass> majorKlassList = new ArrayList<>();
//            for (Element element : options) {
//                MajorKlass majorKlass = new MajorKlass();
//                if(element.val().equals("")) {
//                    continue;
//                }
//                majorKlass.setDmmc(element.text());
//                majorKlass.setDm(element.val());
//                majorKlassList.add(majorKlass);
//            }
//            return majorKlassList;
        return ResultVOUtil.success(departmentWebRepository.findBySchoolId("2"));
    }
    @PostMapping("/getDepartmentForMajor")
    @ApiOperation("获得内蒙古科技大学的专业")
    public ResultVO getDepartmentForMajor(@ApiParam("token") @RequestParam("token") String token,
                             @RequestParam("cookie") String cookie,
                             @RequestParam("yuanxi") String department,
                             @ApiParam("上课年级-->年级，如2016，2017，2018") @RequestParam(value = "nj") String nj){
        //http://202.207.80.11/xkAction.do?actionType=6
        Map<String,String> cookies = new HashMap<>();
        Map<String, String> datas = new HashMap<>();  //参数
        String[] array = cookie.split("=");
        cookies.put(array[0],array[1]);
        Connection con2 = Jsoup
                .connect("http://202.207.80.11/bjkbcxAction.do?oper=ld");
        con2.header("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");
        // 设置cookie和post上面的map数据
        //获得当前学期
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        String currXueqi = (year - 1) + "-" + year+"-2";
        if (month > 7 || month < 2) {   //日期
            currXueqi = year + "-" + (year + 1)+"-1";
        }
        datas.put("bjxnxq",currXueqi+"-1");
        datas.put("bjxsh",department);
        datas.put("pageSize","20");
        datas.put("page","1");
        datas.put("currentPage","1");
        datas.put("bjzyh","");
        datas.put("nj",nj);
        datas.put("bj","");
        datas.put("pageNo","");
        try {
            Connection.Response login = con2.ignoreContentType(true).method(Connection.Method.POST)
                 .data(datas).cookies(cookies).timeout(10000).execute();
            Document document = login.parse();
          //  System.out.println(document.toString());
            Elements elements = document.getElementsByTag("select");
            Element e  = elements.get(2);   //获取院系
            Elements options = e.getElementsByTag("option");
            List<MajorKlass> majorKlassList = new ArrayList<>();
            for (Element element : options) {
                MajorKlass majorKlass = new MajorKlass();
                if(element.val().equals("")) {
                    continue;
                }
                majorKlass.setDmmc(element.text());
                majorKlass.setDm(element.val());
                majorKlassList.add(majorKlass);
            }
            return ResultVOUtil.success(majorKlassList);
        }catch (Exception e){
            e.printStackTrace();
            return ResultVOUtil.error(ResultEnum.GET_MAJOR_ERROR.getCode(),ResultEnum.GET_MAJOR_ERROR.getMessage());
        }
    }
    @PostMapping("/getMajorKlass")
    @ApiOperation("根据内蒙古科技大学的专业获取课表")
    public ResultVO getMajorKlass(@ApiParam("token") @RequestParam("token") String token,
                                  @RequestParam("cookie") String cookie,
                                  @ApiParam("学期") @RequestParam("xueqi") String xueqi,
                                  @ApiParam("院系") @RequestParam("yuanxi") String yuanxi,
                                  @ApiParam("专业") @RequestParam("zhuanye") String zhuanye,
                                  @ApiParam("年级") @RequestParam("nianji") String nianji) {
        Map<String, String> datas = new HashMap<>(); // 参数
        datas.put("bjxnxq", xueqi+"-1"); // 学期
        datas.put("bjxsh", yuanxi); // 院系
        datas.put("bjzyh", zhuanye); // 专业
        datas.put("nj", nianji); // 年级
        datas.put("bj", "");
        datas.put("pageSize", "20");
        datas.put("page", "1");
        datas.put("currentPage", "1");
        datas.put("pageNo", "");
        Map<String, String> cookies = new HashMap<>(); // cookies
        String[] array = cookie.split("=");
        cookies.put(array[0],array[1]);
        try {
//		http://202.207.80.11/bjkbcxAction.do?oper=bjkb_lb
            //教务系统那边的设定，一定要先访问一下这块资源
            Connection tempConn = Jsoup.connect("http://202.207.80.11/bjkbcxAction.do?oper=bjkb_lb");
            tempConn.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");
            // 设置cookie和post上面的map数据
            Connection.Response demo = tempConn.ignoreContentType(true).method(Connection.Method.GET)
                    .cookies(cookies).timeout(10000).execute();
            Document documentDemo = demo.parse();
            if (documentDemo.text().length() == 0) {
                System.err.println("未登录");
                return ResultVOUtil.error(ResultEnum.LOGIN_SCHOOL_ERROR.getCode(), ResultEnum.LOGIN_SCHOOL_ERROR.getMessage());
            }
            // -----------------------------------------------------------------
            Connection con2 = Jsoup.connect("http://202.207.80.11/bjkbcxAction.do?oper=kbtjcx");
            con2.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");
            // 设置cookie和post上面的map数据
            Connection.Response login = con2.ignoreContentType(true).method(Connection.Method.POST).data(datas)
                    .cookies(cookies).execute();
            Document document = login.parse();
            Elements trElements = document.getElementsByClass("odd");
            List<MajorKlassContent> majorKlassContents = new ArrayList<>();
            for (Element element : trElements) {
                Elements tdElements = element.getElementsByTag("td");
                System.err.println(tdElements.get(2).text()); // 得到需要的班级号或者班级名
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append("http://202.207.80.11/bjKbInfoAction.do?oper=bjkb_xx&");
                stringBuilder.append("xzxjxjhh=" + xueqi + "-1");  //这里记得特殊处理下
                stringBuilder.append("&xbjh=" + URLEncoder.encode(tdElements.get(2).text(), "GBK")); // 拼接参数。
                Connection con = Jsoup.connect(stringBuilder.toString());
                con.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");
                // 设置cookie和post上面的map数据
                Connection.Response klasstableConn = con.ignoreContentType(true).method(Connection.Method.GET)
                        .cookies(cookies).timeout(10000).execute();
                Document klasstable = klasstableConn.parse();

                Element table = klasstable.getElementById("user");
                System.out.println(table.toString());
                Elements tableTr = table.getElementsByTag("tr"); // 获得表格的每一行
                int number = 1; // 节次
                int week = 1; // 星期
                MajorKlassContent majorKlassContent = new MajorKlassContent();
                majorKlassContent.setMajor(tdElements.get(2).text());  //专业课表实体类
                List<NewKlassContent> newKlassContentsList = new ArrayList<>();
                for (int i = 0; i < tableTr.size(); i++) {
                    System.err.println(tableTr.get(i).getElementsByTag("td").text());
                    if (i == 0 | i == 1 | i == 6 | i == 11) { // 忽略不必要的表格
                        continue;
                    }
                    if (week > 7) {
                        week = 1;
                    }
                    Elements tableTd = tableTr.get(i).getElementsByTag("td");
                    for (int j = 0; j < tableTd.size(); j++) {
                        if (i == 2 | i == 7 | i == 12) {
                            if (j == 0 | j == 1) {
                                continue;
                            }
                        }
                        if (tableTd.get(j).text().length() == 0) { // 无内容
                            week++;
                            continue;
                        }
                        if (j == 0) {
                            continue;
                        }

                        System.out.print("这是星期：" + week + "  ");
                        System.out.println("这是节次：" + number);
                        System.out.println("课程： " + tableTd.get(j).text());
                        // 这里才是真正的数据解析成实体类了
                        String klassDetailStr = tableTd.get(j).text()
                                .replace("  ", "").replace("  ", "");
                        if (klassDetailStr.indexOf(" ") != -1) {
                            if (!String.valueOf(klassDetailStr.charAt(klassDetailStr.indexOf(" ") - 1)).equals(")")) {
                                klassDetailStr = klassDetailStr
                                        .replace(klassDetailStr.substring(klassDetailStr.indexOf(" "),
                                                klassDetailStr.indexOf(" ") + 2)
                                                , klassDetailStr.substring(klassDetailStr.indexOf(" ") + 1, klassDetailStr.indexOf(" ") + 2));
                            }
                        }
                        String[] klassDetail = klassDetailStr.split(" ");
                        for (String string : klassDetail) {
                            System.out.println("课程：" + string);
                            NewKlassContent newKlassContent = new NewKlassContent();
                            newKlassContent.setDay(week);
                            newKlassContent.setStart(number);
                            newKlassContent.setStep(1);
                            string = string.replace("(", " ");
                            string = string.replace(")", "");
                            String[] klassContentArrays1 = string.split(" ");  //把左括号做成空格来切割
                            newKlassContent.setName(klassContentArrays1[0]); // 课程名字
                            String[] klassContentArrays2 = klassContentArrays1[1].split(",");
                            String classRoom = ("空".equals(klassContentArrays2[1])) ? "" : klassContentArrays2[1]; // 是否为空
                            newKlassContent.setRoom(klassContentArrays2[0] + classRoom);
                            newKlassContent.setTeacher(klassContentArrays2[2]);
                            String weeklistStr = "";
                            for (int z = 3; z < klassContentArrays2.length; z++) {
                                weeklistStr = weeklistStr + "," + klassContentArrays2[z];
                            }
                            newKlassContent.setWeekList(StrToListForIntUtil.getList(weeklistStr));
                            newKlassContentsList.add(newKlassContent);
                            System.out.println(newKlassContent);
                        }
                        week++;
                    }
                    number++;
                }
                majorKlassContent.setNewKlassContentList(newKlassContentsList);
                majorKlassContents.add(majorKlassContent);
            }
            return ResultVOUtil.success(majorKlassContents);
        }catch(Exception e){
            e.printStackTrace();
            return ResultVOUtil.error(ResultEnum.GET_CLASS_ERROR.getCode(),ResultEnum.GET_CLASS_ERROR.getMessage());
        }
    }

    @PostMapping("/getGrade")
    @ApiOperation("根据学期获取成绩")
    public ResultVO getGrade(@ApiParam("token") @RequestParam("token") String token,
                             @ApiParam("日期-例子:<br>2017-2018-2<br>2017-2018-1<br>2018-2019-1") @RequestParam(value = "xnxqh",defaultValue = "") String xnxqh,
                             @RequestParam("cookie") String cookie
    ) {
        String[] array = cookie.split("=");
        Map<String,String> cookies = new HashMap<String,String>();
        cookies.put(array[0],array[1]);
        Connection con = Jsoup.connect("http://202.207.80.11/gradeLnAllAction.do?type=ln&oper=fa");   //间接去获取成绩的地址
        con.header("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");// 配置模拟浏览器
        Connection.Response rs ;
        try {
            rs = con.ignoreContentType(true)
                    .method(Connection.Method.GET)
                    .ignoreHttpErrors(true)
                    .cookies(cookies)
                    .execute();// 获取响应
            Document indexDocument =  rs.parse();
            System.out.println(rs.statusCode());
            Elements iframeElement = indexDocument.getElementsByTag("iframe");
            String gradeUrl = "http://202.207.80.11/"+iframeElement.get(0).attr("src");
            Connection.Response greadeConn =  Jsoup.connect(gradeUrl).ignoreContentType(true)
                                                .method(Connection.Method.GET)
                                                .ignoreHttpErrors(true)
                                                .cookies(cookies)
                                                .execute();// 获取响应
            Document document = greadeConn.parse();
            Element element = document.getElementById("user");
			Elements trElements = element.getElementsByTag("tr");
			List<CrawlerGradeDTO> crawlerGradeDTOs = new ArrayList<>();
			CrawlerResultDTO crawlerResultDTO = new CrawlerResultDTO();
			for(int i = 1; i<trElements.size();i++) {
				Elements  tdElements = trElements.get(i).getElementsByTag("td");
					CrawlerGradeDTO crawlerGradeDTO = new CrawlerGradeDTO();
					crawlerGradeDTO.setKlassName(tdElements.get(2).text());
					crawlerGradeDTO.setKlassType(tdElements.get(5).text());
					crawlerGradeDTO.setGrade(tdElements.get(6).text());
					crawlerGradeDTO.setCredit(tdElements.get(4).text());
					crawlerGradeDTOs.add(crawlerGradeDTO);
			}
			Elements tableElements = document.getElementsByTag("table");
			crawlerResultDTO.setG_Credit(tableElements.get(6).text().substring(tableElements.get(6).text().indexOf("总学分: ")+5, tableElements.get(6).text().indexOf(" 已修读课程门数")));
			crawlerResultDTO.setM_Credit(tableElements.get(7).text().substring(tableElements.get(7).text().indexOf(":")+1, tableElements.get(7).text().indexOf(" 学期总学时")));
			crawlerResultDTO.setCrList(crawlerGradeDTOs);
		    return ResultVOUtil.success(crawlerResultDTO);
        }catch(Exception e){
            e.printStackTrace();
            return ResultVOUtil.error(ResultEnum.LOGIN_SCHOOL_ERROR.getCode(),ResultEnum.LOGIN_SCHOOL_ERROR.getMessage());
        }
    }
}
